前幾天完成了一個簡單發送認證碼的 LIFF APP,其實還有很多可以優化的地方,像是在送出 Request 前,需要先檢查使用者輸入的是否為有效的電子郵件地址,以及提供過一段時間後重新發送的功能。
要判斷一個電子郵件地址是否合法,必須要先知道電子郵件地址是由三個部分組成的 {local}@{domain}
:
A-Z
, a-z
, 0-9
, 但大寫字母在某些郵件伺服器可能被拒絕,或者一律視為小寫.
但不能出現在首尾,也不能連續出現(若在引號內則不受限制)+
或 -
後面的字元可忽略,也就是說只要 +
或 -
前面的字元相同,便有可能指向同一個收件地址A-Z
, a-z
, 0-9
, -
,其中 -
不能出現在首尾,且頂級域名不可全部由數字組成。以上是大略統整的規則,更詳細的規則可參考 RFC 5322 (3.2.3 & 3.4.1), RFC 5321 和 RFC 3696,網路上也有很多整理好的 RFC 簡易原則文章。
看完以上這段,就可以發現如果要重新打造一個精準驗證電子郵件地址是否合法的判斷式,是非常複雜且耗時的一件事,為了不重複造輪子,這邊還是使用套件進行驗證吧~
yup 是一個 JavaScript 的內容驗證套件,有不少套件或框架已經在使用它。
Yup is a JavaScript schema builder for value parsing and validation. Define a schema, transform a value to match, validate the shape of an existing value, or both. Yup schema are extremely expressive and allow modeling complex, interdependent validations, or value transformations.
Yup's API is heavily inspired by Joi, but leaner and built with client-side validation as its primary use-case. Yup separates the parsing and validating functions into separate steps. cast() transforms data while validate checks that the input is the correct shape. Each can be performed together (such as HTML form validation) or seperately (such as deserializing trusted data from APIs).
要使用就必須先在我們的 Vue Project 安裝
npm install -S yup
因為我們先前已經把表單處理的邏輯都拆開放到 BindMailForm.vue,所以只要修改這個檔案即可。修改重點在送出表單前,先檢查郵件地址是否合法。
<script setup>
import {onMounted, ref, defineEmits} from 'vue'
import {sendValidationCodePost} from '/src/service/api'
// import yup
import * as yup from 'yup';
const userName = ref("");
const userToken = ref("");
const userEmail = ref("");
const inputEmail = ref("");
const emit = defineEmits(['nextStep'])
// define mail validate schema
const mailSchema = yup.string().email().required();
const submit = async (mail) => {
// validate mail before send
const isMailValid = await mailSchema.isValid(mail);
if (isMailValid) {
sendValidationCodePost(userName.value, mail, userToken.value)
.then((res) => {
console.log("res: ", res);
const result = res.data.message;
emit('nextStep', result);
})
.catch((err) => {
console.log("err: ", err);
});
} else {
alert('請輸入有效的信箱地址');
}
}
onMounted(() => {
liff.ready.then(() => {
const user = liff.getDecodedIDToken();
userName.value = user && user.name;
userToken.value = user && user.sub;
userEmail.value = user && user.email;
})
})
</script>
<template>
<template v-if="userEmail">
<p>將發送身份認證碼到 {{ userEmail }}</p>
<button type="button" class="btn" @click="submit(userEmail)">確定</button>
</template>
<template v-else>
<p>發送身份認證碼到 <input type="email" v-model="inputEmail" placeholder="請輸入 Email"></p>
<button type="button" class="btn" @click="submit(inputEmail)">確定</button>
</template>
</template>
一樣儲存後 npm run build
產生靜態檔案,並上傳到 Github Page,就可以在驗證碼小幫手檢驗成果了~